// ***************************************************************************************
// Copyright (c) 2023-2025 Peng Cheng Laboratory
// Copyright (c) 2023-2025 Institute of Computing Technology, Chinese Academy of Sciences
// Copyright (c) 2023-2025 Beijing Institute of Open Source Chip
//
// iEDA is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//
// See the Mulan PSL v2 for more details.
// ***************************************************************************************
#include "tcl_ipl.h"

#include <glog/logging.h>

#include "IdbInstance.h"
#include "idm.h"
#include "ipl_io.h"
#include "log/Log.hh"
#include "tool_manager.h"
namespace tcl {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerAutoRun::CmdPlacerAutoRun(const char* cmd_name) : TclCmd(cmd_name)
{
  auto* file_name_option = new TclStringOption(TCL_CONFIG, 1, nullptr);
  addOption(file_name_option);
}

unsigned CmdPlacerAutoRun::check()
{
  TclOption* file_name_option = getOptionOrArg(TCL_CONFIG);
  LOG_FATAL_IF(!file_name_option);
  return 1;
}

unsigned CmdPlacerAutoRun::exec()
{
  if (!check()) {
    return 0;
  }

  TclOption* option = getOptionOrArg(TCL_CONFIG);
  auto data_config = option->getStringVal();

  if (iplf::tmInst->autoRunPlacer(data_config)) {
    std::cout << "iPL run successfully." << std::endl;
  }

  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerFiller::CmdPlacerFiller(const char* cmd_name) : TclCmd(cmd_name)
{
  auto* file_name_option = new TclStringOption(TCL_CONFIG, 1, nullptr);
  addOption(file_name_option);
}

unsigned CmdPlacerFiller::check()
{
  TclOption* file_name_option = getOptionOrArg(TCL_CONFIG);
  LOG_FATAL_IF(!file_name_option);
  return 1;
}

unsigned CmdPlacerFiller::exec()
{
  if (!check()) {
    return 0;
  }

  TclOption* option = getOptionOrArg(TCL_CONFIG);
  auto data_config = option->getStringVal();

  if (iplf::tmInst->runPlacerFiller(data_config)) {
    std::cout << "iPL filler run successfully." << std::endl;
  }

  return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerIncrementalFlow::CmdPlacerIncrementalFlow(const char* cmd_name) : TclCmd(cmd_name)
{
  auto* file_name_option = new TclStringOption(TCL_CONFIG, 1, nullptr);
  addOption(file_name_option);
}

unsigned CmdPlacerIncrementalFlow::check()
{
  TclOption* file_name_option = getOptionOrArg(TCL_CONFIG);
  LOG_FATAL_IF(!file_name_option);
  return 1;
}

unsigned CmdPlacerIncrementalFlow::exec()
{
  if (!check()) {
    return 0;
  }

  TclOption* option = getOptionOrArg(TCL_CONFIG);
  auto data_config = option->getStringVal();

  if (iplf::tmInst->runPlacerIncrementalFlow(data_config)) {
    std::cout << "iPL incremental flow run successfully." << std::endl;
  }

  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerIncrementalLG::CmdPlacerIncrementalLG(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerIncrementalLG::check()
{
  return 1;
}

unsigned CmdPlacerIncrementalLG::exec()
{
  if (not check()) {
    return 0;
  }
  auto* inst = iplf::PlacerIO::getInstance();
  inst->runIncrementalLegalization();
  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerCheckLegality::CmdPlacerCheckLegality(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerCheckLegality::check()
{
  return 1;
}

unsigned CmdPlacerCheckLegality::exec()
{
  auto* inst = iplf::PlacerIO::getInstance();
  bool flag = inst->checkLegality();

  if (flag) {
    std::cout << "Current Placement is Legal" << std::endl;
    return 1;
  } else {
    std::cout << "Current Placement is Not Legal" << std::endl;
    return 0;
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerInit::CmdPlacerInit(const char* cmd_name) : TclCmd(cmd_name)
{
  addOption(new TclStringOption(TCL_CONFIG, 1, nullptr));
}

unsigned CmdPlacerInit::check()
{
  LOG_FATAL_IF(!getOptionOrArg(TCL_CONFIG));
  return 1;
}

unsigned CmdPlacerInit::exec()
{
  if (not check()) {
    return 0;
  }
  auto* config_json = getOptionOrArg(TCL_CONFIG)->getStringVal();
  auto* inst = iplf::PlacerIO::getInstance();
  inst->initPlacer(config_json);
  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerDestroy::CmdPlacerDestroy(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerDestroy::check()
{
  return 1;
}

unsigned CmdPlacerDestroy::exec()
{
  auto* inst = iplf::PlacerIO::getInstance();
  inst->destroyPlacer();
  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerRunGP::CmdPlacerRunGP(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerRunGP::check()
{
  return 1;
}

unsigned CmdPlacerRunGP::exec()
{
  if (not check()) {
    return 0;
  }
  auto* inst = iplf::PlacerIO::getInstance();
  inst->runGlobalPlacement();
  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerRunMP::CmdPlacerRunMP(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerRunMP::check()
{
  return 1;
}

unsigned CmdPlacerRunMP::exec()
{
  if (not check()) {
    return 0;
  }
  auto* inst = iplf::PlacerIO::getInstance();
  inst->runMacroPlacement();
  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerRunLG::CmdPlacerRunLG(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerRunLG::check()
{
  return 1;
}

unsigned CmdPlacerRunLG::exec()
{
  if (not check()) {
    return 0;
  }
  auto* inst = iplf::PlacerIO::getInstance();
  inst->runLegalization();
  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerRunDP::CmdPlacerRunDP(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerRunDP::check()
{
  return 1;
}

unsigned CmdPlacerRunDP::exec()
{
  if (not check()) {
    return 0;
  }
  auto* inst = iplf::PlacerIO::getInstance();
  inst->runDetailPlacement();
  return 1;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CmdPlacerReport::CmdPlacerReport(const char* cmd_name) : TclCmd(cmd_name)
{
}

unsigned CmdPlacerReport::check()
{
  return 1;
}

unsigned CmdPlacerReport::exec()
{
  if (not check()) {
    return 0;
  }
  auto* inst = iplf::PlacerIO::getInstance();
  inst->reportPlacement();
  return 1;
}

}  // namespace tcl
